// 设置localstorage

let res, node, textEle, rectEle;
// 获取画布
let svg = document.getElementById("svg");
// 获得textEditEle编辑元素
let textEditEle = document.getElementById("text-edit");
// 获得工具栏元素
let toolsBar = document.querySelector(".tools-bar");

// 单击选中的svg元素,目的是给这个svg元素添加下级、上级节点等
let parentNode = null;
// 单击选中的svg元素svg元素的类名
let eventClassName = null;

// 子树的根元素应当移动的距离
// let centerDistan = 0;

// svg元素的id号最大值
let idContainer = { svgNode: 0 };

// 创建一个存放node节点的数组，元素的class和节点的id是一一对应关系
let nodeArr = [];

// translateX元素水平间距，translateY垂直间距的一半
let translateX = 90, translateY = 30;

// 创建根节点
let mRootNode = new MindNode();
mRootNode.data.id = "svgNode" + idContainer.svgNode++;
mRootNode.data.type = "root";
nodeArr.push(mRootNode);




function createNodeEle(node, selecNode, opaType) {
    // 创建g分组元素
    let g = document.createElementNS("http://www.w3.org/2000/svg", "g");
    g.setAttribute("id", `svgNode${node.data.id}`);
    svg.appendChild(g);
    node.tempData.g = g;

    // 创建rect矩形元素
    let rectEle = document.createElementNS("http://www.w3.org/2000/svg", "rect");
    g.appendChild(rectEle);
    node.tempData.rectEle = rectEle;
    node.data.textFontSize = "14px";//节点字体大小



    // 创建text文本元素
    let textEle = document.createElementNS("http://www.w3.org/2000/svg", "text");
    g.appendChild(textEle);
    node.tempData.textEle = textEle;
    textEle.setAttribute("class", node.data.id);
    textEle.setAttribute("style", `font-family:"Verdana";font-size:${node.data.textFontSize};line-height:1.5em;fill:#fefefe;`);
    //设置text文本元素内容
    textEle.innerHTML = node.data.text;

    //使rect元素尺寸自适应text文本元素内容
    ctrRectSize(textEle, rectEle, node);//使rect元素尺寸自适应text文本内容


    if (node.isRoot()) {//根节点
        node.data.rectX = 0;//矩形元素x坐标
        node.data.rectY = 225;//矩形元素y坐标       
    }
    if (selecNode) {
        // 如果是插入节点的操作
        if (opaType == 'insertChild') {
            node.data.rectX = node.parent.data.rectX + parseInt(node.parent.data.rectWidth) + translateX;
            let children = selecNode.children;
            let len = children.length;
            if (len == 0) {
                node.data.rectY = node.parent.data.rectY + Math.round(parseInt(node.parent.data.rectHeight) / 2 - parseInt(node.data.rectHeight) / 2);
            } else {
                let centerDistan = recurTransMain(selecNode);
                recurTransSub(selecNode, centerDistan);
                if (selecNode.data.type != "root") {
                    let parentOfSelec = selecNode;
                    // 找到根节点
                    while (!parentOfSelec.parent.isRoot()) {
                        parentOfSelec = parentOfSelec.parent;
                    }

                    let index = parentOfSelec.parent.children.indexOf(parentOfSelec);
                    for (let i = 0; i < index; i++) {
                        recurTransMain(parentOfSelec.parent.children[i], centerDistan);
                    }
                    for (let i = index + 1; i < parentOfSelec.parent.children.length; i++) {
                        recurTransMain(parentOfSelec.parent.children[i], -centerDistan);
                    }
                }
                // 找到node上一个兄弟元素所有子节点中下面的节点
                let lastNode = children[len - 1];
                while (lastNode.children.length !== 0) {
                    lastNode = lastNode.children[lastNode.children.length - 1];
                }

                node.data.rectY = lastNode.data.rectY + parseInt(lastNode.data.rectHeight) + 2 * translateY;
            }
            selecNode.children.push(node);
        }
    }



    if (selecNode) {
        if (opaType == 'insertUpper') {//此时是节点水平位置的变化，selecNode是node的子元素 
            node.data.rectX = selecNode.data.rectX;
            node.data.rectY = selecNode.data.rectY;
            recurTransAfter(selecNode, node);
        }
    }

    // 创建path
    createPath(node);

    rectEle.setAttribute("class", node.data.id);
    rectEle.setAttribute("x", node.data.rectX);
    rectEle.setAttribute("y", node.data.rectY);
    rectEle.setAttribute("rx", "6");//设置圆角
    rectEle.setAttribute("ry", "6");
    rectEle.setAttribute("style", "fill:#5ba6da");




    // 根据矩形元素rect的位置确定text元素位置
    node.data.textX = node.data.rectX + 7;
    node.data.textY = Math.round(node.data.rectY + node.data.rectHeight / 2 + parseInt(node.data.textFontSize) / 3);
    textEle.setAttribute("x", node.data.textX);
    textEle.setAttribute("y", node.data.textY);


    // 设置textEditEle编辑元素
    textEditEle.setAttribute("min-height", Math.round(1.5 * parseInt(node.data.textFontSize)) + "px");

    // 表示此节点的text文本是否发生变化，认为如果textarea打开，文本内容就有可能发生变化
    node.data.flag = false;

    // 为生成的g元素绑定click事件
    gClick(g, rectEle);

    // 给矩形元素和文本元素添加双击响应事件：双击时textarea出现，可编辑文本
    addDblEvent(g, rectEle, textEditEle, textEle, node);



    // 重绘path
    for (let i = 0; i < nodeArr.length; i++) {
        let path = nodeArr[i].tempData.path;
        if (path) {
            svg.removeChild(path);
        }
        createPath(nodeArr[i]);
    }

    return { node, textEle, rectEle };

}


// 创建path元素
function createPath(node) {
    if (!node.isRoot()) {// 非根节点元素有对应的path
        let path = document.createElementNS("http://www.w3.org/2000/svg", "path");
        svg.appendChild(path);
        node.tempData.path = path;
        path.setAttribute("class", node.data.id);
        // path起点
        let x0 = node.parent.data.rectX + Math.round(parseInt(node.parent.data.rectWidth));
        let y0 = node.parent.data.rectY + Math.round(parseInt(node.parent.data.rectHeight) / 2);
        // path终点
        let x2 = node.data.rectX;
        let y2 = node.data.rectY + Math.round(parseInt(node.data.rectHeight) / 2);
        //path控制点    
        let x1, y1;
        if (y0 == y2) {
            x1 = Math.round((x0 + x2) / 2);
            y1 = Math.round((y0 + y2) / 2);

        }
        if (y2 > y0) {
            x1 = Math.round((x0 + x2) / 2);
            y1 = Math.round(9 * (y0 + y2) / 16);
        }
        if (y2 < y0) {
            x1 = Math.round((x0 + x2) / 2);
            y1 = Math.round(7 * (y0 + y2) / 16);
        }
        node.data.pathData = [x0, y0, x1, y1, x2, y2];
        // 设置path元素的坐标
        path.setAttribute("d", `M${x0} ${y0} Q${x1} ${y1} ${x2} ${y2}`);
        // 设置path样式
        path.setAttribute("fill", "none");
        path.setAttribute("stroke", "#5ba6da");
    }
}

// 为g元素绑定click事件
function gClick(g, rectEle) {
    g.addEventListener("click", function (event) {
        event = event || window.event;
        event.stopPropagation();//阻止click事件冒泡到rect
        rectEle.setAttribute("stroke", "#333");
        rectEle.setAttribute("stroke-width", "2");
    });
}

// 控制rect元素尺寸
function ctrRectSize(textEle, rectEle, node) {
    bbox = textEle.getBBox();
    // 根据text内容设置rect的宽度和高度; 30是最小宽度     
    rectEle.setAttribute("width", bbox.width ? Math.round(bbox.width) + 14 : 30);
    rectEle.setAttribute("height", bbox.height ? Math.round(bbox.height) + 10 : node.data.rectHeight);
    node.data.rectWidth = rectEle.getAttribute("width");
    node.data.rectHeight = rectEle.getAttribute("height");
}

// 为rect元素和text元素绑定dblclick事件
function addDblEvent(Ele, rectEle, textEditEle, textEle, node) {
    Ele.addEventListener("dblclick", function () {
        setStyle(rectEle, textEditEle, textEle, node);
    }
    );
}

function setStyle(rectEle, textEditEle, textEle, node) {
    // 判断text里面是否有除了空白之外的内容        
    let str = textEle.innerHTML.trim().length == 0 ? " " : textEle.innerHTML.trim();
    textEditEle.style.display = "block";
    textEditEle.innerText = str;

    //使得div中的文字处于选中状态
    let selection = window.getSelection();
    selection.removeAllRanges();
    let range = document.createRange();
    range.selectNodeContents(textEditEle); // 需要选中的dom节点
    selection.addRange(range);

    node.data.flag = true;//文字可能更改了

    // 根据矩形元素rect的位置确定text元素位置
    node.data.textX = node.data.rectX + 7;
    node.data.textY = Math.round(node.data.rectY + node.data.rectHeight / 2 + parseInt(node.data.textFontSize) / 3);

    // 根据text元素位置确定textarea元素的位置
    textEditEle.style.left = node.data.textX + 95 + "px";//95是svg元素的margin-left
    textEditEle.style.top = node.data.textY + 38 + 35 + "px";//38+35是导航条高度+svg元素的margin-top
    // 设置textarea字体大小和text保持一致
    textEditEle.style.fontSize = node.data.textFontSize;
    textEditEle.style.lineHeight = 1.5 * parseInt(textEditEle.style.fontSize) + "px";
    // 设置rect轮廓线
    rectEle.setAttribute("stroke", "#333");
    rectEle.setAttribute("stroke-width", "2");
}

// document元素只用绑定一次click事件就好
//点击所有的地方textEditEle消失,如果之前打开过textEditEle，则更新text元素的内容
document.addEventListener("click", () => {
    if (node.data.flag) { //更新text元素的内容            
        textEle.innerHTML = textEditEle.innerText.trim();
        let befWidth = node.data.rectWidth; //文本未改变时，rect的宽度
        ctrRectSize(textEle, rectEle, node); //文本改变后，改变rect的宽高
        let diff = node.data.rectWidth - befWidth;//rect宽度变化值
        // 根据diff，设置以这个节点为根节点的子树上所有后代节点的位置
        for (let i = 0; i < node.children.length; i++) {
            recurTransAfter(node.children[i], node, diff);
        }
        //重画连接线 
        textChangePath(node);
        node.data.flag = false;
    }
    textEditEle.style.display = "none";
    rectEle.setAttribute("stroke", "none");
    // 此时未选中任何svg元素？？？万一是点了其它svg元素呢？
    parentNode = null;
    eventClassName = null;
});

function textChangePath(node) {
    // 根据文字变化重画path元素
    let children = node.children;
    let len = children.length;
    for (let i = 0; i < len; i++) {
        let path = children[i].tempData.path;
        if (path) {
            svg.removeChild(path);
        }
        createPath(children[i], children[i].tempData.g, svg);
        textChangePath(children[i]);
    }
}


// 工具栏toolsBar元素添加事件
toolsBar.addEventListener("click", (event) => {
    event = event || window.event;
    event.stopPropagation();//阻止click事件冒泡到tools-bar
});

// text-Edit元素添加事件
textEditEle.addEventListener("click", function (event) {
    event = event || window.event;
    event.stopPropagation();//阻止click事件冒泡到textEditEle
});

// 调整下级子节点的位置
function recurTransMain(selecNode, centerDistan) {
    // SelecNode是根节点的情况
    // 如果要插入的下级节点的上一个兄弟节点有子节点，则该下级节点的位置为：
    // 该兄弟节点最下面的子节点的位置+固定间距
    let len = selecNode.children.length;
    if (typeof (centerDistan) == "undefined") {
        if (!selecNode.children[len - 1].isLeaf()) {//如果不是叶子节点
            // 找到y坐标最大的那个节点
            let children = selecNode.children[len - 1].children;
            let maxYNode = children[children.length - 1];

            while (maxYNode.children.length !== 0) {
                children = maxYNode.children;
                maxYNode = children[children.length - 1];
            }
            // 如果上面节点位置都不变化，要插入的节点node的y坐标如下：
            let nodeY = maxYNode.data.rectY + parseInt(maxYNode.data.rectHeight) + 2 * translateY;
            // 原则是：selecNode的位置不发生变化
            // 计算新的selecNode所有子节点的中点
            let center = Math.round((selecNode.children[0].data.rectY + nodeY + parseInt(selecNode.children[0].data.rectHeight)) / 2);
            // 计算selecNode应当向下移动的距离，要使得selecNode不发生移动，则其余节点向相反方向移动相同距离
            centerDistan = center - selecNode.data.rectY - Math.round(parseInt(selecNode.data.rectHeight) / 2);
        } else {
            let nodeY = selecNode.children[len - 1].data.rectY + parseInt(selecNode.children[len - 1].data.rectHeight) + 2 * translateY;
            let center = Math.round((selecNode.children[0].data.rectY + nodeY + parseInt(selecNode.children[0].data.rectHeight)) / 2);
            centerDistan = center - selecNode.data.rectY - Math.round(parseInt(selecNode.data.rectHeight) / 2);
        }
    }
    for (let i = 0; i < len; i++) { //其所在层之后的节点位置变化,跟随父节点的位置变化而变化               
        selecNode.children[i].data.rectY -= centerDistan;
        let transform = selecNode.children[i].tempData.g.getAttribute("transform");
        if (!transform) {
            selecNode.children[i].tempData.g.setAttribute("transform", `translate(0 ${- centerDistan})`);
        } else {
            selecNode.children[i].tempData.g.setAttribute("transform", `${transform} translate(0 ${- centerDistan})`);
        }
        recurTransMain(selecNode.children[i], centerDistan);
    }
    return centerDistan;
}


function recurTransSub(selecNode, centerDistan) {//调整兄弟节点及上级父节点位置   
    if (!selecNode.isRoot()) {//如果要插入子节点的节点不是root节点
        let parentOfSelec = selecNode.parent;
        let selecArr = parentOfSelec.children;
        //得到selecNode在selecArr中的位置
        let index = selecArr.indexOf(selecNode);
        let len = selecArr.length;

        for (let i = 0; i < index; i++) {//元素上移
            selecArr[i].data.rectY -= centerDistan;
            let transform = selecArr[i].tempData.g.getAttribute("transform");
            if (!transform) {
                selecArr[i].tempData.g.setAttribute("transform", `translate(0 ${- centerDistan})`);
            } else {
                selecArr[i].tempData.g.setAttribute("transform", `${transform} translate(0 ${- centerDistan})`);
            }

        }
        for (let i = index + 1; i < len; i++) {//元素下移
            selecArr[i].data.rectY += centerDistan;
            let transform = selecArr[i].tempData.g.getAttribute("transform");
            if (!transform) {
                selecArr[i].tempData.g.setAttribute("transform", `translate(0 ${centerDistan})`);
            } else {
                selecArr[i].tempData.g.setAttribute("transform", `${transform} translate(0 ${centerDistan})`);
            }
        }

        if (len > 1) {
            // 计算parentSelec位置center
            let center = Math.round((selecArr[len - 1].data.rectY + selecArr[0].data.rectY) / 2 + (selecArr[0].data.rectHeight - parentOfSelec.data.rectHeight) / 2);
            let transDistance = center - parentOfSelec.data.rectY;//parentSelec应当移动的距离
            parentOfSelec.data.rectY = center;
            let transform = parentOfSelec.tempData.g.getAttribute("transform");
            if (!transform) {
                parentOfSelec.tempData.g.setAttribute("transform", `translate(0 ${transDistance})`);
            } else {
                parentOfSelec.tempData.g.setAttribute("transform", `${transform} translate(0 ${transDistance})`);
            }
        } else {//父节点只有一个子节点，那么父节点和子节点的垂直位置保持相同
            let transDistance = selecArr[len - 1].data.rectY - parentOfSelec.data.rectY + Math.round((selecArr[len - 1].data.rectHeight - parentOfSelec.data.rectHeight) / 2);
            parentOfSelec.data.rectY += transDistance;
            let transform = parentOfSelec.tempData.g.getAttribute("transform");
            if (!transform) {
                parentOfSelec.tempData.g.setAttribute("transform", `translate(0 ${transDistance})`);
            } else {
                parentOfSelec.tempData.g.setAttribute("transform", `${transform} translate(0 ${transDistance})`);
            }
        }
        recurTransSub(parentOfSelec, centerDistan);
    }
}

function recurTransAfter(selecNode, node, diff) {//插入上级节点
    let flag = false;
    if (typeof (diff) == "undefined") {//说明是插入上级节点，否则是节点内容变化
        diff = translateX + parseInt(node.data.rectWidth);
        flag = true;
    }

    selecNode.data.rectX += diff;

    let transform = selecNode.tempData.g.getAttribute("transform");
    if (!transform) {
        selecNode.tempData.g.setAttribute("transform", `translate(${diff} 0)`);
    } else {
        selecNode.tempData.g.setAttribute("transform", `${transform} translate(${diff} 0)`);
    }


    let selecChildArr = selecNode.children;
    let len = selecChildArr.length;
    for (let i = 0; i < len; i++) {
        if (flag) {//插入上级节点
            recurTransAfter(selecChildArr[i], node);
        } else {//文本长度发生变化
            recurTransAfter(selecChildArr[i], node, diff);
        }
    }
}




// 如果没有本地存储的话，直接新建根节点元素
res = createNodeEle(mRootNode);//调用节点生成函数
node = res.node;
textEle = res.textEle;
rectEle = res.rectEle;